package com.lifp.service;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baidu.aip.face.AipFace;
import com.baidu.aip.face.FaceVerifyRequest;
import com.baidu.aip.util.Base64Util;
import com.lifp.config.BaiDuAiSDKFaceConfig;
import com.lifp.dto.BaiDuFaceImageRegisterDTO;
import com.lifp.entity.BaiDuFaceUser;
import com.lifp.enums.ImageTypeEnum;
import com.lifp.vo.Result;
import lombok.SneakyThrows;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description SDK 方式，人脸库接口
 * @Author lifp
 * @Date 2023/2/26
 * @Version 1.0
 */
@Service
public class BaiDuAiSDKFaceLibraryService {
    @Autowired
    private AipFace aipFace;
    @Autowired
    private BaiDuAiSDKFaceConfig config;

    /**
    * 人脸注册接口
    */
    public Result registerFace(BaiDuFaceImageRegisterDTO imageRegisterDTO) {
        JSONObject jsonObject = aipFace.addUser(
                imageRegisterDTO.getImage(),
                ImageTypeEnum.BASE64.getCode(),
                config.getDefaultFaceGroupId(),
                imageRegisterDTO.getUser_id(),
                null);

        if(!jsonObject.isNull("error_msg") && "SUCCESS".equals(jsonObject.get("error_msg"))){
            HashMap<String, Object> result = (HashMap<String, Object>)((JSONObject) jsonObject.get("result")).toMap();
            return Result.ok(result,"注册成功");
        }
        return Result.error(jsonObject.get("error_msg"));
    }

    /**
     * 人脸更新接口
     */
    public Result updateUser(BaiDuFaceImageRegisterDTO imageRegisterDTO) {
        JSONObject jsonObject = aipFace.updateUser(
                imageRegisterDTO.getImage(),
                ImageTypeEnum.BASE64.getCode(),
                config.getDefaultFaceGroupId(),
                imageRegisterDTO.getUser_id(),
                null);

        if(!jsonObject.isNull("error_msg") && "SUCCESS".equals(jsonObject.get("error_msg"))){
            HashMap<String, Object> result = (HashMap<String, Object>)((JSONObject) jsonObject.get("result")).toMap();
            return Result.ok(result,"更新成功");
        }
        return Result.error(jsonObject.get("error_msg"));
    }

    /**
    * 人脸登录接口
    *   先进行活体检测
    *   再进行人脸比对
    */
    public Result loginByFaceImg64(String img64){
        BaiDuFaceUser baiDuFaceUser = searchAndFilter(img64);

        if(baiDuFaceUser != null){
            //todo 结合user_id,进行数据库比对，下发token，完成登录
            String user_id = baiDuFaceUser.getUser_id();

            return Result.ok(user_id,"登录成功！");
        }
        return Result.error("认证失败，请重试!");
    }

    /**
     * 人脸登录接口
     *   先进行活体检测
     *   再进行人脸比对
     */
    @SneakyThrows
    public Result loginByFaceImgFile(MultipartFile file){
        //图片文件转BASE64
        String img64 = Base64Util.encode(file.getBytes());

        BaiDuFaceUser baiDuFaceUser = searchAndFilter(img64);

        if(baiDuFaceUser != null){
            //todo 结合user_id,进行数据库比对，下发token，完成登录
            String user_id = baiDuFaceUser.getUser_id();

            return Result.ok(user_id,"登录成功！");
        }
        return Result.error("认证失败，请重试!");
    }

    /**
     *@Description 根据人脸照片，进行筛选
     *@param img64
     *@Return
     */
    private BaiDuFaceUser searchAndFilter(String img64){
        //1.进行活体检测
        List verifyRequestList = new ArrayList<FaceVerifyRequest>();
        verifyRequestList.add(new FaceVerifyRequest(img64,ImageTypeEnum.BASE64.getCode()));

        JSONObject faceverify = aipFace.faceverify(verifyRequestList);

        if(!faceverify.isNull("error_msg") && "SUCCESS".equals(faceverify.get("error_msg"))){
            Double face_liveness = Double.valueOf(
                    String.valueOf(
                            ((JSONObject) faceverify.get("result")).get("face_liveness")
                    )
            );

            //识别分数判断，80分以上
            if(face_liveness < 0.8){
                return null;
            }

            //2.进行人脸查找
            JSONObject jsonObject = aipFace.search(img64, ImageTypeEnum.BASE64.getCode(), config.getDefaultFaceGroupId(), null);
            if(!faceverify.isNull("error_msg") && "SUCCESS".equals(faceverify.get("error_msg"))){
                //拿到识别到的集合
                JSONArray jsonArray = new JSONArray((((JSONObject) jsonObject.get("result")).get("user_list")).toString());
                List<BaiDuFaceUser> baiDuFaceUsers = JSONUtil.toList(jsonArray, BaiDuFaceUser.class);

                if(baiDuFaceUsers == null || baiDuFaceUsers.size()<1){
                    return null;
                }

                //筛选
                List<BaiDuFaceUser> resultList = baiDuFaceUsers.stream()
                        .filter(item->{
                            //筛选出80分以上的
                            return item.getScore().compareTo(BigDecimal.valueOf(80)) >0;
                        })
                        .sorted((x, y) -> {
                            //根据score 由高到低排序
                            return y.getScore().compareTo(x.getScore());
                        }).collect(Collectors.toList());


                //得到最终筛选结果
                BaiDuFaceUser baiDuFaceUser = resultList.get(0);
                return baiDuFaceUser;
            }
        }
        return null;
    }
}
